package cn.tedu.mall.seckill.controller;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.JsonResult;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.pojo.seckill.dto.SeckillOrderAddDTO;
import cn.tedu.mall.pojo.seckill.vo.SeckillCommitVO;
import cn.tedu.mall.seckill.exception.SeckillBlockHandler;
import cn.tedu.mall.seckill.exception.SeckillFallback;
import cn.tedu.mall.seckill.service.ISeckillService;
import cn.tedu.mall.seckill.utils.SeckillCacheUtils;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/seckill")
@Api(tags = "执行秒杀模块")
public class SeckillController {

    @Autowired
    private ISeckillService seckillService;
    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/{randCode}")
    @ApiOperation("验证随机码并提交秒杀订单")
    @ApiImplicitParam(value = "随机码",name="randCode",required = true)
    @PreAuthorize("hasRole('user')")
    @SentinelResource(value = "提交秒杀订单",
            blockHandlerClass = SeckillBlockHandler.class,
            blockHandler = "seckillBlock",
            fallbackClass = SeckillFallback.class,
            fallback = "seckillFallback")
    public JsonResult<SeckillCommitVO> commitSeckill(
            @PathVariable String randCode,
            @Validated SeckillOrderAddDTO seckillOrderAddDTO){
        // 获取spuId值
        Long spuId=seckillOrderAddDTO.getSpuId();
        // 下面的目标是将这个spuId对应的预热在缓存中的随机码获取
        String randCodeKey= SeckillCacheUtils.getRandCodeKey(spuId);
        // 上面获取对应的key,下面就判断这个key是否存在于Redis中
        if(redisTemplate.hasKey(randCodeKey)){
            // 如果Redis中有这个key,就要从redis中获取随机码的值
            String redisRandCode=redisTemplate
                    .boundValueOps(randCodeKey).get()+"";
            // 判断前端传入的随机码和预热的随机码是否一致
            if(! redisRandCode.equals(randCode)){
                //  进入if表示随机码不一致,要抛异常
                throw new CoolSharkServiceException(
                        ResponseCode.NOT_FOUND,
                        "随机码不正确(实际开发中不要这样提示)");
            }
            // 程序运行到这表示随机码匹配,下面就提交秒杀订单
            SeckillCommitVO commitVO=seckillService
                    .commitSeckill(seckillOrderAddDTO);
            // 一切正常,返回值给前端
            return JsonResult.ok(commitVO);
        }else{
            //Redis中没有这个key直接报异常
            throw new CoolSharkServiceException(
                    ResponseCode.NOT_FOUND,
                    "没有找到当前商品的随机码(过一分钟再试)");
        }
    }
}
